<script setup lang="ts">
import type { BasicClassValueField } from "@@/apis/basic-data/types"
import type { ComponentTableData, ModelDetailInfo } from "@@/apis/entity/type"
import type { FormInstance, FormRules } from "element-plus"
import type { VxeTablePropTypes } from "vxe-table"
import { addEntityModelApi, getComponentApi, getComponentFieldApi, getEntityModelApi, updateEntityModelApi } from "@@/apis/entity"
import { FormTypeEnum, ModelTypeOps } from "@@/constants/other-keys"
import { ElMessage, ElMessageBox } from "element-plus"
import { cloneDeep } from "lodash-es"
import { computed, ref, watch } from "vue"
import { useRoute } from "vue-router"
import { isEmpty, isEqual } from "xe-utils"
import "@@/components/plugins/TypingValueBfModal"

interface Props {
  id: string | undefined
  dialogType: FormTypeEnum
  visible: boolean
}
const props = withDefaults(defineProps<Props>(), {
  dialogType: FormTypeEnum.VIEW
})
const emit = defineEmits(["closeDialog"])
const route = useRoute()
const DEFAULT_FORM_DATA: ModelDetailInfo = {
  typing: {
    id: props.id,
    entityId: route.query.id as string,
    modelType: undefined,
    label: undefined,
    samplingRate: undefined,
    functionId: undefined
  },
  values: []
}
const isEdit = ref<boolean>(false)
function validatePass(rule: any, value: any, callback: any) {
  if (isEmpty(value)) {
    callback()
  } else if (!value) {
    callback(new Error("请输入数字"))
  } else if (!/^\d+$/.test(value)) {
    callback(new Error("只能输入数字"))
  } else {
    callback()
  }
}
const dialogVisible = ref<boolean>(false)
const formRef = ref<FormInstance | null>(null)
const formData = ref<ModelDetailInfo>(cloneDeep(DEFAULT_FORM_DATA))
const formRules: FormRules<ModelDetailInfo> = {
  "typing.label": [{ required: true, trigger: "blur", message: "请输入" }],
  "typing.modelType": [{ required: true, trigger: "change", message: "请选择" }],
  "typing.functionId": [{ required: true, trigger: "change", message: "请选择" }],
  "typing.samplingRate": [{ validator: validatePass, trigger: "change", message: "请输入数字" }]
}
const validValuesRules = ref<VxeTablePropTypes.EditRules>({
  value: [{ required: true, message: "值不能为空" }]
})
const columnConfig: VxeTablePropTypes.ColumnConfig = {
  resizable: true
}
const loading = ref<boolean>(false)
const detailLoading = ref<boolean>(false)
const textMap = computed(() => {
  if (props.dialogType == FormTypeEnum.CREATE) return "添加模型"
  else return "查看详情"
})
const componentList = ref<ComponentTableData[]>([])
const componentOptions = ref<ComponentTableData[]>([])
const componentLoading = ref<boolean>(false)
const defData = ref<ModelDetailInfo>()

function getComponentData(): Promise<ComponentTableData[]> {
  return new Promise((resolve) => {
    getComponentApi().then(({ data }) => {
      resolve(data)
    })
  })
}
function remoteMethod(query: string) {
  if (query) {
    componentLoading.value = true
    setTimeout(() => {
      componentLoading.value = false
      componentOptions.value = componentList.value.filter((item) => {
        return (!isEmpty(item.code) && item.code.toLowerCase().includes(query.toLowerCase()))
          || (!isEmpty(item.name) && item.name.toLowerCase().includes(query.toLowerCase()))
          || (!isEmpty(item.description) && item.description.toLowerCase().includes(query.toLowerCase()))
      })
    }, 200)
  } else {
    componentOptions.value = componentList.value
    componentLoading.value = false
  }
}
async function showDialog() {
  formRef.value?.resetFields()
  componentList.value = await getComponentData()
  componentOptions.value = componentList.value
  detailLoading.value = false
  isEdit.value = false
  if (props.dialogType != FormTypeEnum.CREATE) {
    getEntityModel()
  }
}
function getEntityModel() {
  detailLoading.value = true
  props.id && getEntityModelApi(props.id)
    .then(async ({ data }) => {
      formData.value = cloneDeep(data)
      if (formData.value.values == undefined || formData.value.values.length == 0) {
        handleSelectComponent(formData.value.typing.functionId)
      }
    })
    .finally(() => {
      detailLoading.value = false
    })
}
function handleConfirm() {
  formRef.value?.validate(async (valid: boolean, fields) => {
    if (!valid) return console.error("表单校验不通过", fields)
    loading.value = true
    const api = props.dialogType == FormTypeEnum.CREATE ? addEntityModelApi : updateEntityModelApi
    api(formData.value)
      .then(() => {
        ElMessage.success("操作成功")
        emit("closeDialog", "refresh")
      })
      .finally(() => {
        loading.value = false
      })
  })
}
function handleCloseTip(done: () => void) {
  if (isEqual(defData.value, formData.value)) {
    ElMessageBox.confirm("当前编辑未保存，是否确定关闭？").then(() => {
      done()
    })
  } else {
    done()
  }
}
function closeDialog() {
  formRef.value?.resetFields()
  formData.value.values = []
  emit("closeDialog", "refresh")
}
function handleSelectComponent(value: string) {
  getComponentFieldApi({
    componentId: value,
    staticFlag: 1
  }).then(({ data }) => {
    formData.value.values = []
    data.forEach((item) => {
      const field: BasicClassValueField = {
        field: item,
        functionFieldId: undefined,
        id: undefined,
        typingId: undefined,
        value: ""
      }
      formData.value.values.push(field)
    })
  })
}
function handleEdit() {
  defData.value = cloneDeep(formData.value)
  isEdit.value = true
}
function handleEditCancel() {
  isEdit.value = false
  getEntityModel()
}
function handleEditSave() {
  formRef.value?.validate(async (valid: boolean, fields) => {
    if (!valid) return console.error("表单校验不通过", fields)
    loading.value = true
    updateEntityModelApi(formData.value)
      .then(() => {
        ElMessage.success("操作成功")
        emit("closeDialog", "refresh")
      })
      .finally(() => {
        loading.value = false
      })
  })
}
const componentTextMap = computed<{ [propName: string]: string }>(
  () => {
    return componentOptions.value.reduce(
      (acc: { [propName: string]: string }, curr) => {
        acc[curr.id] = curr.code
        return acc
      },
      {}
    )
  }
)

watch(
  () => [props.id, props.dialogType, props.visible],
  () => {
    dialogVisible.value = props.visible
    if (props.visible) {
      showDialog()
    }
  }
)
</script>

<template>
  <el-drawer
    v-model="dialogVisible" direction="rtl" size="900" :before-close="handleCloseTip" :show-close="false"
    @close-auto-focus="closeDialog" @close="closeDialog"
  >
    <template #header>
      <div class="drawer-header">
        <h4>{{ textMap }}</h4>
        <el-space>
          <el-button v-if="isEdit" @click="handleEditCancel">
            取消保存
          </el-button>
          <el-button v-if="isEdit" type="primary" v-throttle="() => handleEditSave()">
            保存
          </el-button>
          <el-button v-if="!isEdit && props.dialogType == FormTypeEnum.VIEW" type="primary" @click="handleEdit">
            编辑
          </el-button>
        </el-space>
      </div>
    </template>
    <template #default>
      <el-form
        ref="formRef" :model="formData" :rules="formRules" :close-on-click-modal="false" label-width="100px"
        label-position="right" v-loading="detailLoading"
      >
        <div class="cpi-header">
          <div class="cpi-header-text">
            基本信息
          </div>
        </div>
        <template v-if="dialogType != FormTypeEnum.VIEW || isEdit">
          <el-row>
            <el-col :sm="12">
              <el-form-item label="组件模型" prop="typing.functionId">
                <el-select
                  v-model="formData.typing.functionId" popper-class="drawer-select-popper" placeholder="请选择"
                  filterable :filter-method="remoteMethod" clearable @clear="formData.values = []"
                  @change="handleSelectComponent"
                >
                  <el-option v-for="item in componentOptions" :key="item.id" :label="item.code" :value="item.id" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :sm="12">
              <el-form-item label="类型" prop="typing.modelType">
                <el-select
                  v-model="formData.typing.modelType" popper-class="drawer-select-popper" placeholder="请选择"
                  clearable
                >
                  <el-option v-for="item in ModelTypeOps" :key="item.value" :label="item.value" :value="item.value" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :sm="12">
              <el-form-item label="标签" prop="typing.label">
                <el-input v-model="formData.typing.label" autocomplete="off" placeholder="请输入" />
              </el-form-item>
            </el-col>
            <el-col :sm="12">
              <el-form-item label="采样率" prop="typing.samplingRate">
                <el-input v-model.number="formData.typing.samplingRate" autocomplete="off" placeholder="请输入数字" />
              </el-form-item>
            </el-col>
          </el-row>
        </template>
        <template v-else>
          <el-row>
            <el-col :sm="12">
              <el-form-item label="组件模型：" prop="typing.functionId">
                {{ componentTextMap[formData.typing.functionId] }}
              </el-form-item>
            </el-col>
            <el-col :sm="12">
              <el-form-item label="类型：" prop="typing.modelType">
                {{ formData.typing.modelType }}
              </el-form-item>
            </el-col>
            <el-col :sm="12">
              <el-form-item label="标签：" prop="typing.label">
                {{ formData.typing.label }}
              </el-form-item>
            </el-col>
            <el-col :sm="12">
              <el-form-item label="采样率：" prop="typing.samplingRate">
                {{ formData.typing.samplingRate }}
              </el-form-item>
            </el-col>
          </el-row>
        </template>
        <div class="cpi-header">
          <div class="cpi-header-text">
            参数
          </div>
        </div>
        <div class="drawertable-content">
          <vxe-table ref="valuesTableRef" class="drawer-table" :column-config="columnConfig" show-overflow="tooltip" height="auto" keep-source :edit-rules="validValuesRules" :data="formData.values" :edit-config="{ trigger: 'click', mode: 'row', showStatus: true }">
            <vxe-table-column field="field.catalogId" :visible="false" />
            <vxe-table-column type="seq" title="序号" align="center" width="60" />
            <vxe-table-column field="field.code" title="参数名" />
            <vxe-table-column field="field.name" title="参数描述" />
            <vxe-table-column field="field.type" title="分类" formatter="formatType" />
            <vxe-table-column field="field.typeCode" title="数据类型" />
            <vxe-table-column
              v-if="isEdit" field="value" title="值" width="300" formatter="formatValue"
              :cell-render="{ name: 'TypingValueBfModal' }"
            />
            <vxe-table-column v-else field="value" title="值" width="300" formatter="formatValue" />
          </vxe-table>
        </div>
      </el-form>
    </template>
    <template #footer>
      <div class="dialog-footer">
        <el-button plain @click="closeDialog">
          取 消
        </el-button>
        <el-button :loading="loading" type="primary" @click="handleConfirm">
          确 定
        </el-button>
      </div>
    </template>
  </el-drawer>
</template>

<style lang="scss" scoped>
.cpi-header-text {
  color: #fff !important;
}

:deep(.el-drawer__body) {
  width: 100%;
  height: 100%;
}

.el-form {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.drawertable-content {
  flex: 1;
}
</style>
